home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / minix / up1510b.tgz / up1510b / src / commands / cgrep.c < prev    next >
C/C++ Source or Header  |  1990-07-23  |  9KB  |  374 lines

  1. /* cgrep - grep and display context    Author: Mark Mallet */
  2.  
  3. /*
  4.         Nov 19 1984     Mark Mallett   (mem@zinn.MV.COM)
  5.  
  6. mem    860224    Modified to do r/e (regular expression) parsing on unix
  7. mem    860324    Added -f, -n; added code to number lines correctly on output.
  8. mem    870325    Added support for regcmp()/regex() style regular expression
  9.   library; redid some conditionals to provide better mix'n'match.
  10. mem    870326    Don't try to print the filename if reading from stdin.
  11.   Add -w option.  Fix a small problem which occasionally allowed
  12.   the separator to come out between adjacent lines of the file.
  13. mem    871119    Fix semantics of call to regcmp(): the NULL terminating the
  14.   argument list was missing.  It worked, but probably only
  15.   due to some bizarre coincidence.
  16. dro    890109  Minor mods to compile under Minix
  17.  
  18. */
  19.  
  20. #define  OS_UNIX        /* Define this for unix systems */
  21.  /* #define    REGEX *//* Define this for re_comp/re_exec library */
  22. #define  REGCMP            /* Define this to use regcmp/regex */
  23.  /* #define    OS_CPM *//* Define this for CP/M-80 */
  24.  
  25.  
  26. /* Don't touch these */
  27. #define    NOREGEXP        /* Set this for no regular expression */
  28. #ifdef    REGEX
  29. #undef    NOREGEXP
  30. #endif    /* REGEX */
  31.  
  32. #ifdef    REGCMP
  33. #undef    NOREGEXP
  34. #endif    /* REGCMP */
  35.  
  36.  
  37. #ifdef OS_CPM
  38. #include "stdio.h"
  39. #include "ctype.h"
  40. #endif /* OS_CPM */
  41.  
  42. #ifdef OS_UNIX
  43. #include <sys/types.h>
  44. #include <sys/dir.h>        /* Either here or in sys directory - dro */
  45. #include <ctype.h>
  46. #include <limits.h>        /* should have this                - dro */
  47. #include <regexp.h>        /* should have this                - dro */
  48. #include <stdlib.h>
  49. #include <stdio.h>
  50. #endif /* OS_UNIX */
  51.  
  52.  
  53. /* Local definitions */
  54.  
  55. #ifndef    NULL
  56. #define    NULL    ((char *)0)
  57. #endif    /* NULL */
  58.  
  59. #ifndef NUL
  60. #define NUL     '\000'
  61. #endif
  62.  
  63. #ifndef TRUE
  64. #define TRUE    1
  65. #define FALSE   0
  66. #endif
  67.  
  68.  
  69. /* Internal data declared global */
  70.  
  71.  
  72. /* Internal routines */
  73.  
  74.  
  75. /* External data */
  76.  
  77.  
  78. /* Local data */
  79.  
  80. static int Debug = {FALSE};    /* Debug enabled flag */
  81. static int Lcur = {0};        /* Current line (in Lines array) */
  82. static char **Lines = {(char **) NULL};    /* Lines pointer array */
  83. static int Linlen = {100};    /* Line length */
  84. static int Lone = {0};        /* Line one (in Lines array) */
  85. static int Nmr = {0};        /* Number of matched regions */
  86. static char *Pat = {NULL};    /* Pattern */
  87. static char Shwfile = {TRUE};    /* Show file name... */
  88. static char Shwline = {TRUE};    /* Show line number */
  89. static int Waft = {0};        /* Window after */
  90. static int Wbef = {0};        /* Window before */
  91. static int Wsiz = {0};        /* Window size */
  92.  
  93. regexp *Re;            /* Result from reg compilation */
  94.  
  95. main(argc, argv)
  96. int argc;            /* Argument count */
  97. char **argv;            /* Argument values */
  98.  
  99. {
  100.   int i;            /* Scratch */
  101.   int n;            /* Scratch again */
  102.   int c;            /* A character */
  103.   char *aptr;            /* Argument pointer */
  104.   int nf;            /* number of files on command line */
  105.  
  106.   nf = 0;            /* No files on line */
  107.  
  108.   for (i = 1; i < argc; i++) {    /* Look at args */
  109.     if (argv[i][0] != '-') {/* If option */
  110.         if (Pat == NULL) {    /* If no pattern yet given */
  111.             Pat = argv[i];    /* point here */
  112. #ifdef    REGEX
  113.             if ((Re = re_comp(Pat)) != NULL) {
  114.                 fprintf(stderr, "cgrep: %s\n", re);
  115.                 exit(1);
  116.             }
  117. #endif    /* REGEX */
  118.  
  119. #ifdef    REGCMP
  120.             if ((Re = regcomp(Pat)) == NULL) {
  121.                 fprintf(stderr, "cgrep: error in regular expression.\n");
  122.                 exit(1);
  123.             }
  124. #endif    /* REGCMP */
  125.  
  126.         } else {    /* This must be a file to search */
  127.             nf++;    /* Count it */
  128.             dosrch(argv[i]);    /* Search */
  129.         }
  130.     } else {        /* Option char */
  131.         c = argv[i][1];    /* Get option char */
  132.         if (isupper(c))    /* Trap idiot definition of tolower */
  133.             c = tolower(c);    /* Don't care about case */
  134.         n = i;
  135.         aptr = NULL;    /* Find arg, if any */
  136.         if (argv[i][2] != NUL) {
  137.             aptr = &argv[i][2];
  138.             n = i;    /* Where to set i if we use this arg */
  139.         } else if (i < argc - 1) {    /* use next.. */
  140.             n = i + 1;
  141.             aptr = argv[n];
  142.         }
  143.         switch (c) {    /* Process the option */
  144.             case 'a':    /* Lines after */
  145.             Waft = atoi(aptr);
  146.             Lines = NULL;
  147.             i = n;
  148.             break;
  149.  
  150.             case 'b':    /* Lines before */
  151.             Wbef = atoi(aptr);
  152.             Lines = (char **) NULL;
  153.             i = n;
  154.             break;
  155.  
  156. /* Disable debug output
  157.                     case 'd':    Debug = TRUE;                     break;
  158. */
  159.  
  160.             case 'f':    /* Suppress filename on output */
  161.             Shwfile = FALSE;
  162.             break;
  163.  
  164.             case 'l':    /* Line length */
  165.             Linlen = atoi(aptr);
  166.             Lines = NULL;
  167.             i = n;
  168.             break;
  169.  
  170.             case 'n':    /* Suppress line number on output */
  171.             Shwline = FALSE;
  172.             break;
  173.  
  174.             case 'w':    /* Window: lines before and after */
  175.             Waft = Wbef = atoi(aptr);
  176.             Lines = NULL;
  177.             i = n;
  178.             break;
  179.  
  180.             default:
  181.             fprintf(stderr, "Invalid option %s\n", argv[i]);
  182.             exit(1);
  183.         }
  184.     }
  185.   }
  186.  
  187.   if (Pat == NULL) {        /* If no pattern given */
  188.     fprintf(stderr,
  189.         "Usage: cgrep [-a n] [-b n] [-f] [-l n] [-n] [-w n] pattern [filename... ]\n");
  190.     exit(1);
  191.   }
  192.   if (nf == 0)            /* No files processed ? */
  193.     dosrch((char *)NULL);        /* Do standard input */
  194. }
  195.  
  196.  /* Dosrch (ifnm) Perform the search 
  197.   * Accepts :
  198.   * 
  199.   * ifn             Input file name
  200.   * 
  201.   * 
  202.   * Returns :
  203.   * 
  204.   * 
  205.   */
  206.  
  207. dosrch(ifnm)
  208. char *ifnm;            /* Input filelname */
  209.  
  210. {
  211.   FILE *ifp;            /* Input fp */
  212.   char *lptr;            /* Line pointer */
  213.   int i;            /* Scratch */
  214.   int prtaft;            /* Print-after count */
  215.   int linnum;            /* Line number */
  216.   int nlb;            /* Number of lines buffered */
  217.  
  218.   if (ifnm != NULL) {        /* If file name given */
  219.     ifp = fopen(ifnm, "r");    /* Open it for read access */
  220.     if (ifp == NULL) {
  221.         fprintf(stderr, "Can not open file %s\n", ifnm);
  222.         return;
  223.     }
  224.   } else
  225.     ifp = stdin;
  226.  
  227.   if (Lines == NULL) {        /* If no line table allocated.. */
  228.     Wsiz = Wbef + 2;    /* Determine total window size */
  229.     Lines = (char **) calloc(Wsiz, sizeof(char *));
  230.     /* Allocate pointer table */
  231.     for (i = 0; i < Wsiz; i++)    /* Allocate line buffers */
  232.         Lines[i] = (char *) calloc(Linlen, sizeof(char));
  233.   }
  234.   Lcur = Lone = 0;        /* Setup line pointers */
  235.   nlb = 0;            /* No lines buffered */
  236.   linnum = 0;            /* Line number is zero */
  237.   prtaft = -(Wbef + 1);        /* Make sure separator given first time */
  238.  
  239.   for (;;) {            /* Loop through the file */
  240.     lptr = Lines[Lcur];    /* Get pointer to current line */
  241.     if (++Lcur == Wsiz)    /* Bump curr pointer and wrap */
  242.         Lcur = 0;    /* if hit end */
  243.     if (Lone == Lcur)    /* If wrapped to beginning of window */
  244.         if (++Lone == Wsiz)    /* Bump beginning */
  245.             Lone = 0;    /* and wrap if hit end */
  246.  
  247.     if (fgets(lptr, Linlen, ifp) != lptr) break;    /* if end of file */
  248.  
  249.     linnum++;        /* Count line number */
  250.     if (matlin(lptr)) {    /* If matching line */
  251.         if (prtaft < (-Wbef))    /* Check for separator needed */
  252.             if ((Nmr++ > 0) && ((Wbef > 0) || (Waft > 0)))
  253.                 printf("----------------------------------------------------------------------------\n");
  254.         while (Lone != Lcur) {    /* Until we close the window */
  255.             shwlin(ifnm, linnum - nlb, Lines[Lone]);
  256.             /* Show the line */
  257.             if (++Lone == Wsiz) Lone = 0;
  258.             nlb--;
  259.         }
  260.         nlb = 0;    /* No lines buffered */
  261.         prtaft = Waft;    /* Print n lines after */
  262.     } else {        /* Didn't match */
  263.         if (prtaft-- > 0) {    /* If must print lines after */
  264.             shwlin(ifnm, linnum, lptr);
  265.             /* Show the line */
  266.             Lone = Lcur;    /* Match pointers */
  267.         } else if (nlb < Wbef)    /* Count lines buffered */
  268.             nlb++;
  269.     }
  270.   }
  271.  
  272.   if (ifnm != NULL) fclose(ifp);
  273. }
  274.  
  275.  /* Shwlin (fnm, linnum, line) Show a matching line 
  276.   * 
  277.   * Accepts :
  278.   * 
  279.   * fnm             File name
  280.   * 
  281.   * linnum          Line number
  282.   * 
  283.   * line            Line to show
  284.   * 
  285.   * 
  286.   * Returns :
  287.   * 
  288.   * 
  289.   */
  290.  
  291. shwlin(fnm, linnum, line)
  292. char *fnm;            /* File name */
  293. int linnum;            /* Line number */
  294. char *line;            /* Line (with newline at end) to print */
  295.  
  296. {
  297.   if (Shwfile && (fnm != NULL)) printf("%s%s", fnm, Shwline ? " " : ":");
  298.   if (Shwline) printf("@%05d%:", linnum);
  299.   printf("%s", line);
  300. }
  301.  
  302.  /* Matlin (line) Perform match against pattern and line 
  303.   * 
  304.   * Accepts :
  305.   * 
  306.   * line            Address of line to match
  307.   * 
  308.   * 
  309.   * Returns :
  310.   * 
  311.   * <value>         TRUE if match FALSE if not
  312.   * 
  313.   * 
  314.   */
  315.  
  316.  
  317. int matlin(line)
  318. char *line;            /* Line to match */
  319.  
  320. {
  321.   int rtncode;            /* Return value from this routine */
  322.  
  323.  
  324. #ifdef    NOREGEXP
  325.   char *pptr, *lptr, *tlptr;
  326.   int c1, c2;
  327. #endif /* NOREGEXP */
  328.  
  329.   if (Debug) printf("Matching %s against %s", Pat, line);
  330.  
  331. #ifdef    REGEX
  332.   rt